package org.client.iot.ui.device.fragment;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;

import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.bin.david.form.core.TableConfig;
import com.bin.david.form.data.format.bg.IBackgroundFormat;
import com.bin.david.form.data.style.FontStyle;
import com.lucky.base.network.NetworkApi;
import com.lucky.base.network.observer.BaseObserver;
import com.lucky.utils.FastjsonUtils;
import com.lucky.utils.log.LogUtils;
import com.xuexiang.xui.utils.WidgetUtils;
import com.xuexiang.xui.widget.dialog.MiniLoadingDialog;
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog;

import org.client.iot.R;
import org.client.iot.databinding.FragmentDeviceDebugBinding;
import org.client.iot.domain.DataInfo;
import org.client.iot.domain.DataListDto;
import org.client.iot.domain.DebugData;
import org.client.iot.domain.DebugOptionsDto;
import org.client.iot.domain.HoleDto;
import org.client.iot.domain.MenuItem;
import org.client.iot.http.ApiService;
import org.client.iot.http.BaseDevReq;
import org.client.iot.ui.device.adapter.AgingDataDetailsAdapter;
import org.client.iot.ui.device.adapter.DeviceDebugAdapter;
import org.client.iot.ui.device.adapter.DeviceDebugDataAdapter;
import org.client.iot.ui.device.debug.AgingActivity;
import org.client.iot.ui.device.debug.CumulativeDisplacementActivity;
import org.client.iot.ui.device.debug.DownHoleActivity;
import org.client.iot.ui.device.debug.InitialValueMeasurementActivity;
import org.tzw.template.base.BaseFragment;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

import io.reactivex.Observable;
import okhttp3.MediaType;
import okhttp3.RequestBody;

public class DeviceDebugFragment extends BaseFragment<FragmentDeviceDebugBinding> {
    private String[] degOptionMenu;
    private DeviceDebugAdapter adapter;
    private DeviceDebugDataAdapter dataAdapter;
    private AgingDataDetailsAdapter mAdapter;
    private List<DataInfo> devChargeInfoVoList = new ArrayList<>();
    private MiniLoadingDialog mMiniLoadingDialog;
    private boolean isBrake = false;
    private MaterialDialog flushDialog;
    private int proId;

    @Override
    protected void initData(View view) {
        degOptionMenu = getResources().getStringArray(R.array.deg_option_menu);
        adapter = new DeviceDebugAdapter(requireActivity(), getMenuList());
        dataAdapter = new DeviceDebugDataAdapter(requireActivity());
        mAdapter = new AgingDataDetailsAdapter(requireActivity());
        LinearLayoutManager manager = new LinearLayoutManager(requireActivity(), LinearLayoutManager.VERTICAL, false);
        mRoot.recDataDeList.setLayoutManager(manager);
        mRoot.recDataDeList.setAdapter(mAdapter);
        mRoot.recDataDeList.addItemDecoration(new DividerItemDecoration(requireActivity(), DividerItemDecoration.VERTICAL));
    }

    private List<DebugData> setDataList(DebugOptionsDto debugOptionsDto) {
        List<DebugData> debugDataList = new ArrayList<>();
        if (debugOptionsDto != null) {
            debugDataList.add(new DebugData("工作模式", debugOptionsDto.getWorkingMode() == null ? "" : debugOptionsDto.getWorkingMode()));
            debugDataList.add(new DebugData("传感器位置(m)", debugOptionsDto.getSensorPositionMeter() + ""));
            debugDataList.add(new DebugData("状态", debugOptionsDto.getDeviceWorkingStatus() == null ? "" : debugOptionsDto.getDeviceWorkingStatus()));
            debugDataList.add(new DebugData("主机电量(%)", debugOptionsDto.getDeviceBatteryPercent() + ""));
            debugDataList.add(new DebugData("传感器电量百分比(%)", debugOptionsDto.getSensorBatteryPercent() + ""));
            debugDataList.add(new DebugData("温度(°C)", debugOptionsDto.getTemperatureCelsius() + ""));
            debugDataList.add(new DebugData("水位(m)", debugOptionsDto.getWaterLevelMeter() + ""));
        }
        return debugDataList;
    }

    @Override
    protected void initView(View view) {
        int spanCount = 4;
        int spacing = 5; // 每个item之间的间距(px)
        boolean includeEdge = true; // 是否在边缘也添加分割线

        mRoot.recDebuggingMenu.setLayoutManager(new GridLayoutManager(requireActivity(), spanCount));
        mRoot.recDebuggingMenu.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge));
        mRoot.recDebuggingMenu.setAdapter(adapter);

        LinearLayoutManager manager = new LinearLayoutManager(requireActivity(), LinearLayoutManager.VERTICAL, false);
        mRoot.recDataList.setLayoutManager(manager);

        mRoot.recDataList.setAdapter(dataAdapter);
        mRoot.recDataList.addItemDecoration(new DividerItemDecoration(requireActivity(), DividerItemDecoration.VERTICAL));
        updateBrakeMenuItem();
        TableConfig tableConfig = mRoot.smartTableData.getConfig();
        FontStyle contentStyle = tableConfig.getContentStyle();
        FontStyle titleStyle = tableConfig.getTableTitleStyle();
        tableConfig.setContentStyle(contentStyle.setTextSize(50));
        tableConfig.setTableTitleStyle(titleStyle.setTextSize(50).setTextColor(R.color.black));
        tableConfig.setShowTableTitle(false);
        tableConfig.setShowXSequence(false);
        tableConfig.setShowYSequence(false);
        tableConfig.setFixedTitle(true);
        tableConfig.setColumnTitleBackground(new HeadBackgroundFormat(R.color.common_primary_color));

    }

    @Override
    public void onResume() {
        super.onResume();
        disLoading();
        showLoading("获取调试参数中...");
        getDebugOptions();
    }

    @Override
    protected void initListener() {
        adapter.setOnItemClickListener((adapter, view, position) -> {
            switch (position) {
                case 0: //标准测量
                    new MaterialDialog.Builder(requireActivity()).iconRes(R.drawable.icon_tip)
                            .title("标准测量").content("是否开始标准测量，测量一旦开始，在测量结束前，将无法人为停止。")
                            .positiveText("确定").onPositive((dialog, which) -> {
                                showLoading("标准测量中..");
                                hole("正常");
                            }).show();
                    break;
                case 1: //初始量取
                    Intent intent = new Intent(requireActivity(), InitialValueMeasurementActivity.class);
                    intent.putExtra("projectId", proId);
                    requireActivity().startActivity(intent);
                    break;
                case 2: //累计位移
                    Intent intent1 = new Intent(requireActivity(), CumulativeDisplacementActivity.class);
                    intent1.putExtra("projectId", proId);
                    requireActivity().startActivity(intent1);
                    break;
                case 3: //刷新状态
                    flushDialog = new MaterialDialog.Builder(requireActivity()).iconRes(R.drawable.icon_tip).limitIconToDefaultSize().title("刷新状态").content("仪器状态同步中...").cancelable(false).progress(true, 0).progressIndeterminateStyle(false).negativeText("取消").show();
                    CompletableFuture.allOf(CompletableFuture.runAsync(this::getDebugOptions), CompletableFuture.runAsync(() -> {
                        //获取测量参数列表
                        Calendar calendar = Calendar.getInstance();
                        calendar.add(Calendar.DAY_OF_YEAR, -3);
                        getDataList("", "", 0, new DataListCallback() {
                            @Override
                            public void onSuccess(int latestId) {
                                // 在这里处理获取到的 latestId
                                LogUtils.i("获取到最新ID", String.valueOf(latestId));
                                proId = latestId;
                            }

                            @Override
                            public void onFailure(Throwable e) {
                                LogUtils.e("获取数据失败", e.getMessage());
                            }
                        });
                    })).thenRun(() -> {
                        requireActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                getDataInfo(proId, 0);
                                disLoading();
                            }
                        });
                    }).exceptionally(ex -> {
                        requireActivity().runOnUiThread(() -> {
                            disLoading();
                            if (flushDialog != null) {
                                flushDialog.dismiss();
                            }

                        });
                        return null;
                    });

                    break;
                case 4: //探孔
                    requireActivity().startActivity(new Intent(requireActivity(), DownHoleActivity.class));
                    break;
                case 5: //刹车
                    if (isBrake) {
                        showLoading("刹车中..");
                        brake("刹车");
                    } else {
                        showLoading("松开刹车中..");
                        brake("松开刹车");
                    }
                    break;
                case 6: //模式切换
                    new MaterialDialog.Builder(requireActivity()).title("模式切换").items(R.array.working_mode).itemsCallbackSingleChoice(0, (dialog, view1, which, text) -> {
                        showToastLong(text.toString());
                        showLoading("模式切换中..");
                        changeWorkingMode(text.toString());
                        return true;
                    }).positiveText("确定").negativeText("取消").show();
                    break;
                case 7: //老化测量
                    requireActivity().startActivity(new Intent(requireActivity(), AgingActivity.class));
                    break;
            }
        });
    }

    private void updateBrakeMenuItem() {
        List<MenuItem> menuList = getMenuList();
        if (!isBrake) {
            // 如果已刹车，显示"松开刹车"的菜单项
            menuList.set(5, new MenuItem("松开刹车", R.drawable.debug_ico_release_brake));
        } else {
            // 如果未刹车，显示"刹车已松开"的菜单项
            menuList.set(5, new MenuItem("刹车已松开", R.drawable.debug_ico_breake));
        }
        adapter.setList(menuList);
        adapter.notifyDataSetChanged();
    }

    private List<MenuItem> getMenuList() {
        List<MenuItem> menuList = new ArrayList<>();
        menuList.add(new MenuItem(degOptionMenu[0], R.drawable.debug_ico_simple_measure));
        menuList.add(new MenuItem(degOptionMenu[1], R.drawable.debug_ico_initial_value));
        menuList.add(new MenuItem(degOptionMenu[2], R.drawable.debug_ico_super_deformation));
        menuList.add(new MenuItem(degOptionMenu[3], R.drawable.debug_ico_flush));
        menuList.add(new MenuItem(degOptionMenu[4], R.drawable.debug_ico_start_exploratory_hole));
        menuList.add(new MenuItem(degOptionMenu[5], R.drawable.debug_ico_release_brake));
        menuList.add(new MenuItem(degOptionMenu[6], R.drawable.debug_ico_model));
        menuList.add(new MenuItem(degOptionMenu[7], R.drawable.debug_ico_aging_measure));
        return menuList;
    }

    public class HeadBackgroundFormat implements IBackgroundFormat {
        private int backgroundColor;

        public HeadBackgroundFormat(int backgroundColor) {
            this.backgroundColor = backgroundColor;
        }

        @Override
        public void drawBackground(Canvas canvas, Rect rect, Paint paint) {
            if (backgroundColor != TableConfig.INVALID_COLOR) {
                paint.setColor(backgroundColor);
                paint.setStyle(Paint.Style.FILL_AND_STROKE);
                canvas.drawRect(rect, paint);
            }
        }
    }

    public static class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

        private int spanCount; // 列数
        private int spacing; // 分割线宽度（px）
        private boolean includeEdge; // 是否在边缘也添加分割线

        public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
            this.spanCount = spanCount;
            this.spacing = spacing;
            this.includeEdge = includeEdge;
        }

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view); // item的位置
            int column = position % spanCount; // 计算列号

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // 计算左边距
                outRect.right = (column + 1) * spacing / spanCount; // 计算右边距

                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item底部边距
            } else {
                outRect.left = column * spacing / spanCount; // 计算左边距
                outRect.right = spacing - (column + 1) * spacing / spanCount; // 计算右边距
                if (position >= spanCount) {
                    outRect.top = spacing; // item顶部边距（除了第一行）
                }
            }
        }
    }

    //测量接口
    private void hole(String model) {
        String params = FastjsonUtils.toJsonString(holeParams(model));
        Observable<BaseDevReq<HoleDto>> compose = NetworkApi.createService(ApiService.class, "dev").hole(RequestBody.create(MediaType.parse("application/json"), params)).compose(NetworkApi.applySchedulers(new BaseObserver<BaseDevReq<HoleDto>>() {
            @SuppressLint({"CheckResult", "SetTextI18n"})
            @Override
            public void onSuccess(BaseDevReq<HoleDto> req) {
                if (req == null) {
                    return;
                }
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    LogUtils.i("测量接口req==", req.toString());
                    showToastLong(req.getMessage());
                    if ("正在测量".equals(req.getMessage())) {
                        hole(model);
                    } else {
                        if (req.getData() != null) {
//                            String dataId = UniqueIdGenerator.generateEncryptedId();
//                            HoleDto holeDto = req.getData();
//                            holeDto.setDataId(dataId);
//                            LauncherApplication.getDaoSession().getHoleDtoDao().insert(holeDto);
                            showLoading("获取详细数据中...");
                            proId = req.getData().getId();
                            getDataInfo(req.getData().getId(), 1);
                        }
                    }

                });

            }

            @SuppressLint("CheckResult")
            @Override
            public void onFailure(Throwable e) {
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    showToastLong(e.getMessage());
                });

            }
        }));
    }

    //松开刹车/刹车
    private void brake(String type) {
        String params = FastjsonUtils.toJsonString(brakeParams(type));
        Observable<BaseDevReq<Object>> compose = NetworkApi.createService(ApiService.class, "dev").brake(RequestBody.create(MediaType.parse("application/json"), params)).compose(NetworkApi.applySchedulers(new BaseObserver<BaseDevReq<Object>>() {
            @SuppressLint({"CheckResult", "SetTextI18n"})
            @Override
            public void onSuccess(BaseDevReq<Object> req) {
                if (req == null) {
                    return;
                }
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    LogUtils.i("松开刹车req==", req.toString());
                    if (req.getMessage() != null) {
                        showToastLong(req.getMessage());
                        if ("刹车已松开".equals(req.getMessage())) {
                            isBrake = true;
                            updateBrakeMenuItem();
                        } else if ("刹车".equals(req.getMessage())) {
                            isBrake = false;
                            updateBrakeMenuItem();
                        }
                    }
                });

            }

            @SuppressLint("CheckResult")
            @Override
            public void onFailure(Throwable e) {
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    showToastLong(e.getMessage());
                });

            }
        }));
    }

    //修改工作模式
    private void changeWorkingMode(String workingMode) {
        String params = FastjsonUtils.toJsonString(changeWorkingModeParams(workingMode));
        Observable<BaseDevReq<Object>> compose = NetworkApi.createService(ApiService.class, "dev").changeWorkingMode(RequestBody.create(MediaType.parse("application/json"), params)).compose(NetworkApi.applySchedulers(new BaseObserver<BaseDevReq<Object>>() {
            @SuppressLint({"CheckResult", "SetTextI18n"})
            @Override
            public void onSuccess(BaseDevReq<Object> req) {
                if (req == null) {
                    return;
                }
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    LogUtils.i("修改工作模式req==", req.toString());
                    if (req.getMessage() != null) {
                        showToastLong(req.getMessage());
                    }
                });

            }

            @SuppressLint("CheckResult")
            @Override
            public void onFailure(Throwable e) {
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    showToastLong(e.getMessage());
                });

            }
        }));
    }

    //获取测量参数列表
    private void getDataList(String start_time, String end_time, int type, DataListCallback callback) {
        Observable<BaseDevReq<List<DataListDto>>> compose = NetworkApi.createService(ApiService.class, "dev").getDataList(start_time, end_time, type).compose(NetworkApi.applySchedulers(new BaseObserver<BaseDevReq<List<DataListDto>>>() {
            @SuppressLint({"CheckResult", "SetTextI18n", "NotifyDataSetChanged"})
            @Override
            public void onSuccess(BaseDevReq<List<DataListDto>> req) {
                if (req == null) {
                    if (callback != null) {
                        callback.onFailure(new Exception("请求返回空数据"));
                    }
                    return;
                }
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    LogUtils.i("获取测量参数列表接口req==", FastjsonUtils.toJsonString(req.getData()));
                    showToastLong(req.getMessage());
                    if (req.getData() != null) {
                        Optional<DataListDto> latestData = req.getData().stream().max(Comparator.comparing(DataListDto::getDataTime));
                        if (latestData.isPresent()) {
                            int latestId = latestData.get().getId();
                            LogUtils.i("最新数据的ID==", String.valueOf(latestId));
                            if (callback != null) {
                                callback.onSuccess(latestId);
                            }
                        } else {
                            if (callback != null) {
                                callback.onFailure(new Exception("没有找到最新数据"));
                            }
                        }

                    } else {
                        if (callback != null) {
                            callback.onFailure(new Exception("数据列表为空"));
                        }
                    }
                });

            }

            @SuppressLint("CheckResult")
            @Override
            public void onFailure(Throwable e) {
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    showToastLong(e.getMessage());
                    if (callback != null) {
                        callback.onFailure(e);
                    }
                });

            }
        }));
    }

    //获取测量参数详情接口
    private void getDataInfo(int id, int type) {
        Observable<BaseDevReq<List<DataInfo>>> compose = NetworkApi.createService(ApiService.class, "dev").getDataInfo(id).compose(NetworkApi.applySchedulers(new BaseObserver<BaseDevReq<List<DataInfo>>>() {
            @SuppressLint({"CheckResult", "SetTextI18n", "NotifyDataSetChanged"})
            @Override
            public void onSuccess(BaseDevReq<List<DataInfo>> req) {
                if (req == null) {
                    return;
                }
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    LogUtils.i("获取测量参数详情接口req==", FastjsonUtils.toJsonString(req.getData()));
                    showToastLong(req.getMessage());
                    if (req.getData() != null) {
                        mAdapter.setList(req.getData());
                        mAdapter.notifyDataSetChanged();
                        devChargeInfoVoList = req.getData();
//                        if (type == 1) {
//                            for (DataInfo dataInfo : req.getData()) {
//                                dataInfo.setDataId(UniqueIdGenerator.generateEncryptedId());
//                                dataInfo.setId(id);
//                                LauncherApplication.getDaoSession().getDataInfoDao().insertInTx(dataInfo);
//                            }
//                        }
                    }
                    if (flushDialog != null) {
                        flushDialog.dismiss();
                    }
                });

            }

            @SuppressLint("CheckResult")
            @Override
            public void onFailure(Throwable e) {
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    showToastLong(e.getMessage());
                });

            }
        }));
    }

    //获取调试参数接口
    private void getDebugOptions() {
        Observable<BaseDevReq<DebugOptionsDto>> compose = NetworkApi.createService(ApiService.class, "dev").getDebugOptions().compose(NetworkApi.applySchedulers(new BaseObserver<BaseDevReq<DebugOptionsDto>>() {
            @SuppressLint({"CheckResult", "SetTextI18n", "NotifyDataSetChanged"})
            @Override
            public void onSuccess(BaseDevReq<DebugOptionsDto> req) {
                if (req == null) {
                    return;
                }
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    LogUtils.i("获取调试参数req==", FastjsonUtils.toJsonString(req.getData()));
                    showToastLong(req.getMessage());
                    if (req.getData() != null) {
                        dataAdapter.setList(setDataList(req.getData()));
                        dataAdapter.notifyDataSetChanged();
                    }
                });

            }

            @SuppressLint("CheckResult")
            @Override
            public void onFailure(Throwable e) {
                requireActivity().runOnUiThread(() -> {
                    disLoading();
                    showToastLong(e.getMessage());
                });

            }
        }));
    }

    private Map<String, Object> changeWorkingModeParams(String workingMode) {
        Map<String, Object> params = new LinkedHashMap<>();
        params.put("workingMode", workingMode);
        return params;
    }

    private Map<String, Object> brakeParams(String type) {
        Map<String, Object> params = new LinkedHashMap<>();
        params.put("type", type);
        return params;
    }

    private Map<String, Object> holeParams(String model) {
        Map<String, Object> params = new LinkedHashMap<>();
        params.put("type", "开始探孔");
        params.put("model", model);
        return params;
    }

    public interface DataListCallback {
        void onSuccess(int latestId);

        void onFailure(Throwable e);
    }

    private void showLoading(String msg) {
        requireActivity().runOnUiThread(() -> {
            mMiniLoadingDialog = WidgetUtils.getMiniLoadingDialog(requireActivity(), msg);
            mMiniLoadingDialog.show();
        });
    }

    private void disLoading() {
        requireActivity().runOnUiThread(() -> {
            if (mMiniLoadingDialog != null) {
                mMiniLoadingDialog.dismiss();
            }
        });

    }

    @Override
    public void onStop() {
        super.onStop();
        disLoading();
        if (flushDialog != null) {
            flushDialog.dismiss();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        disLoading();
        if (flushDialog != null) {
            flushDialog.dismiss();
        }
    }


}